package com.xinlong.shop.core.order.service.impl;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.xinlong.shop.core.goods.entity.Goods;
import com.xinlong.shop.core.goods.service.IGoodsService;
import com.xinlong.shop.core.order.OrderQueryParam;
import com.xinlong.shop.core.order.OrderStatusEnum;
import com.xinlong.shop.core.order.OrderTypeEnum;
import com.xinlong.shop.core.order.entity.Order;
import com.xinlong.shop.core.order.entity.OrderItem;
import com.xinlong.shop.core.order.entity.dto.CreateOrderDTO;
import com.xinlong.shop.core.order.entity.vo.OrderVO;
import com.xinlong.shop.core.order.mapper.OrderMapper;
import com.xinlong.shop.core.order.service.IOrderItemService;
import com.xinlong.shop.core.order.service.IOrderService;
import com.xinlong.shop.core.util.OrderSnTypeEnum;
import com.xinlong.shop.core.util.OrderUtil;
import com.xinlong.shop.framework.exception.ServiceException;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;

/**
 * <p>
 * 订单表 服务实现类
 * </p>
 *
 * @author Sylow
 * @since 2023-07-04
 */
@Service
public class OrderServiceImpl extends ServiceImpl<OrderMapper, Order> implements IOrderService {

    private final IGoodsService goodsService;
    private final OrderUtil orderUtil;
    private final IOrderItemService orderItemService;

    public OrderServiceImpl(IGoodsService goodsService, OrderUtil orderUtil, IOrderItemService orderItemService) {
        this.goodsService = goodsService;
        this.orderUtil = orderUtil;
        this.orderItemService = orderItemService;
    }

    @Override
    public void update(Order order, Integer id) {
        UpdateWrapper<Order> updateWrapper = new UpdateWrapper<>();
        updateWrapper.eq("id", id);
        this.update(order, updateWrapper);
    }
    @Override
    public void delete(Integer id) {
        UpdateWrapper<Order> deleteWrapper = new UpdateWrapper<>();
        deleteWrapper.eq("id", id);
        this.remove(deleteWrapper);
    }

    @Override
    public IPage<Order> selectPage(IPage<Order> page, OrderQueryParam orderQueryParam) {
        QueryWrapper<Order> queryWrapper = new QueryWrapper<>();
        if (orderQueryParam != null) {
            queryWrapper.like(StrUtil.isNotBlank(orderQueryParam.getOrderSn()), "order_sn", orderQueryParam.getOrderSn());
            queryWrapper.eq(orderQueryParam.getOrderType() != null, "order_type", orderQueryParam.getOrderType());
            queryWrapper.like(StrUtil.isNotBlank(orderQueryParam.getMemberMobile()), "member_mobile", orderQueryParam.getMemberMobile());
            queryWrapper.eq(orderQueryParam.getOrderStatus() != null, "order_status", orderQueryParam.getOrderStatus());
            queryWrapper.eq(orderQueryParam.getMemberId() != null, "member_id", orderQueryParam.getMemberId());
            if (orderQueryParam.getBuyTime() != null && orderQueryParam.getBuyTime().length > 1) {
                queryWrapper.ge(orderQueryParam.getBuyTime()[0] != null, "create_time", orderQueryParam.getBuyTime()[0] / 1000);
                queryWrapper.le(orderQueryParam.getBuyTime()[1] != null, "create_time", orderQueryParam.getBuyTime()[1] / 1000);
            }

        }
        queryWrapper.orderByDesc("create_time");

        return this.page(page, queryWrapper);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Order createOrder(CreateOrderDTO createOrderDTO) {

        /**
         * 创建的订单流程
          */
        // 1. 先验证商品是否存在
        List<Goods> goodsList = this.goodsService.listByIds(createOrderDTO.getGoodsIds());
            // 商品查出来的数量和传入的数量不一致，说明有商品不存在
        if (goodsList.size() != createOrderDTO.getGoodsIds().size()) {
            throw new ServiceException("商品不存在");
        }
        // 生成订单号
        String orderSn = orderUtil.getOrderSn(OrderSnTypeEnum.ORDER.getCode());

        BigDecimal totalPrice = new BigDecimal("0");
        List<OrderItem> orderItemList = new ArrayList<>();
        // 2. 验证商品状态 同时创建orderItem
        for (Goods goods : goodsList) {
            // 商品状态不为上架状态，说明商品已下架
            if (goods.getGoodsStatus() != 1) {
                throw new ServiceException("商品已下架");
            }
            // 增加总价
            totalPrice = totalPrice.add(goods.getGoodsPrice());

            OrderItem orderItem = new OrderItem(0, orderSn, goods.getId(),
                    goods.getGoodsName(),
                    goods.getGoodsImgs().get(0),
                    1,
                    goods.getGoodsPrice(),  // 原价
                    goods.getGoodsPrice(),  // 成交价 这里因为还没做促销方式 所以成交价就是商品的正常价格
                    BigDecimal.ZERO,        // 促销金额
                    "",          // 促销信息
                    0,
                    DateUtil.currentSeconds()
            );
            orderItemList.add(orderItem);
        }


        // 这里以后可以增加 促销和运费的代码
        // 以后再增加扣减库存

        // 创建订单
        Order order = new Order(orderSn, OrderTypeEnum.ORDER.getCode(),
                createOrderDTO.getMemberId(),
                createOrderDTO.getMemberName(),
                totalPrice, // 订单总价 // 现在这里没有其他费用，所以订单总价就是商品总价
                totalPrice, // 商品总价
                BigDecimal.ZERO, // 运费
                BigDecimal.ZERO, // 促销金额
                "", // 促销信息
                orderItemList.size(),   // 商品数量
                createOrderDTO.getShipAreaId(),
                createOrderDTO.getShipAreaName(),
                createOrderDTO.getShipFullAddress(),    // 详细地址
                createOrderDTO.getShipName(),   // 收货人姓名
                createOrderDTO.getShipMobile(), // 收货人手机号
                DateUtil.currentSeconds()
        );
        boolean result = this.save(order);
        // 创建订单结果
        if (!result) {
            throw new ServiceException("创建订单失败");
        }
        // 循环插入订单id
        for (OrderItem orderItem : orderItemList) {
            orderItem.setOrderId(order.getId());
        }
        result = this.orderItemService.saveBatch(orderItemList);

        if (!result) {
            throw new ServiceException("创建订单项失败");
        }

        return order;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void paySuccess(String orderSn, String payOrderSn) {
        // 1. 根据订单号查询订单
        Order order = this.getOne(new QueryWrapper<Order>().eq("order_sn", orderSn));
        if (order == null) {
            throw new ServiceException("订单不存在");
        }
        // 2. 修改订单状态
        order.setOrderStatus(OrderStatusEnum.PAID_OFF.getCode());
        order.setPayStatus(1);
        order.setPaymentSn(payOrderSn);
        order.setPaymentTime(DateUtil.currentSeconds());
        this.update(order, new UpdateWrapper<Order>().eq("order_sn", orderSn));
        // 3. 修改订单项状态
        boolean result = this.orderItemService.updateStatus(orderSn, OrderStatusEnum.PAID_OFF.getCode());
        if (!result) {
            throw new ServiceException("修改订单项状态失败");
        }
    }

    @Override
    public IPage<OrderVO> selectPageOrderVo(IPage<OrderVO> page, OrderQueryParam orderQueryParam) {
        return this.baseMapper.pageOrderVo(page, orderQueryParam);
    }

    @Override
    public void shipment(String orderSn, Integer logisticsId, String logisticsName, String logisticsSn) {
        // 1. 根据订单号查询订单
        Order order = this.getOne(new QueryWrapper<Order>().eq("order_sn", orderSn));
        if (order == null) {
            throw new ServiceException("订单不存在");
        }
        // 2. 修改订单状态
        order.setOrderStatus(OrderStatusEnum.SHIPPED.getCode());
        order.setLogisticsId(logisticsId);
        order.setLogisticsName(logisticsName);
        order.setLogisticsSn(logisticsSn);
        order.setShipTime(DateUtil.currentSeconds());
        this.update(order, new UpdateWrapper<Order>().eq("order_sn", orderSn));
        // 3. 修改订单项状态
        boolean result = this.orderItemService.updateStatus(orderSn, OrderStatusEnum.SHIPPED.getCode());
        if (!result) {
            throw new ServiceException("修改订单项状态失败");
        }
    }

}
